home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Comm / mail / SpamFryer.lha / SpamFryer / SpamFryer_Fr.rexx < prev    next >
OS/2 REXX Batch file  |  2004-08-22  |  21KB  |  640 lines

  1. /* sys:rexxc/rx
  2.  *
  3.  *  Checks through emails on a POP3 host and purges the unwanted ones.
  4.  *  $VER: SpamFryer.rexx 3:9 (2004-8-19) by Simon N Goodwin $
  5.  *
  6.  *  »» French version : Herve Dupont - 02/08/2004
  7.  *
  8.  *  SpamFryer.text lists changes since November 2003 Aminet release.
  9.  */
  10.  
  11.    Account. = '' /* resets the array */
  12.    count.1 = 0
  13.    count.2 = 0
  14.  
  15.  
  16.    /*** CONFIGURATION BLOCK **/
  17.    /* Account details can be in the file SpamFryer.accounts, or here in the following format: */       
  18.    /* Account.1.1 = "new.mail.org" */ /* IP number e.g. 194.5.6.7 or domain e.g. mail.isp.net */
  19.    /* Account.1.2 = "username1"    */ /* Your user name - typically your ISP account name     */
  20.    /* Account.1.3 = "password1"    */ /* The login password you use for email - confidential! */   
  21.    /* Continue for Account.2.1, Account 2.2 and Account.2.3 etc if you have several accounts. */
  22.    
  23.    keepList    = 'SpamFryer.keepList'  /* The path and name of your file of details of mails you want to keep */
  24.    loseList    = 'SpamFryer.loseList'  /* The path and name of your file of details of mails you want to lose */
  25.    accountFile = 'SpamFryer.accounts'  /* The file of login details for your POP3 accounts (if not set above) */
  26.  
  27.    logFile     = 'T:SpamFryer.log'     /* Specifies the log file this program generates */
  28.    screenName  = '*'                   /* log window public screen name, '' for no window or '*' for the default */
  29.    lineMax     = 60                    /* The maximum width of subject line characters reported to console */
  30.    noDigits    = 0                     /* Non-zero to lose all mails with digits in their To: address */
  31.  
  32.    /**************************** END OF CONFIGURATION BLOCK ****************************/
  33.  
  34.  
  35.  
  36.  
  37.    OPTIONS results /* Valeur retournée par Arexx lors des retours de fonctions */
  38.  
  39.       
  40.    PARSE ARG quiet .
  41.    IF (UPPER(quiet) == "VERBOSE") THEN
  42.       verbose = 1
  43.    ELSE
  44.       verbose = 0
  45.  
  46.    IF screenName ~='' THEN DO
  47.      CALL close STDOUT
  48.      CALL open(STDOUT, "con:48/48/590/150/SpamFryer3 Log  --  Cliquer le gadget de fermeture une fois terminé/CLOSE/WAIT/SCREEN " screenName, w)
  49.    END
  50.  
  51.    IF logFile ~='' THEN
  52.       IF ~open(log,logFile,'A') THEN
  53.          IF ~open(log,logFile,'W') THEN
  54.             logFile = ''
  55.  
  56.    CALL Check_Accounts
  57.  
  58.    keep    = 1 /* Symbolic category names for readability */
  59.    lose    = 2
  60.    gTo     = 1
  61.    gFrom   = 2
  62.    gReply  = 3
  63.    gSubject= 4
  64.    gEarly  = 5
  65.    gDating = 6 /* Used for combination test, not in list */
  66.    
  67.    /* load the lose and keep lists */
  68.    list.keep = keepList
  69.    list.lose = loseList
  70.    listfield. = 0
  71.    listpattern. = ''
  72.  
  73.  
  74.  
  75.    
  76.    /****************************************************************/
  77.    /* Règles encoquillers, or put them in keeplist and loselist files */
  78.  
  79.    /* Let through mails specifically about this program */
  80.    
  81.    CALL keep_rule "Subject: SpamFryer"
  82.    CALL keep_rule "Subject: Spam Frier" /* Allow various spellings */
  83.    CALL keep_rule "Subject: Spam Fryer"
  84.    
  85.    /* These three rules catch a lot of spam */
  86.    
  87.    CALL lose_rule "Subject: *SPAM*"    /* Premarked by mail server */
  88.    CALL lose_rule "To: www."           /* Idiot mailing web server */
  89.    CALL lose_rule "To: undisclosed-recipients" /* A spam indicator */
  90.    
  91.    /* These all signify a HTML mail with no plain text - i.e. spam */
  92.  
  93.    CALL lose_rule "Early-Ref: </"
  94.    CALL lose_rule "Early-Ref: <HTML>"
  95.    CALL lose_rule "Early-Ref: text/html"
  96.    
  97.    /****************************************************************/
  98.    
  99.    
  100.  
  101.    
  102.    DO type = keep TO lose
  103.      IF list.type ~='' THEN DO     
  104.        IF ~OPEN(list,list.type,'R') THEN DO
  105.          sigh = list.type 'non trouvé.'
  106.          SAY sigh
  107.          IF logFile ~= '' THEN CALL WRITELN(log, sigh)
  108.        END
  109.        ELSE DO
  110.          IF verbose THEN SAY list.type "rules:"
  111.          iterations = 0
  112.          counter = count.type
  113.          DO WHILE ~EOF(list)
  114.            iterations = iterations + 1
  115.            listerror = 0
  116.            CALL learn_rule READLN(list), type
  117.            IF listerror THEN DO
  118.              sigh = 'ERREUR dans' list.type 'ligne' iterations 'sautée(s).'
  119.              SAY sigh
  120.              IF logFile ~= '' & verbose THEN CALL WRITELN(log, sigh)
  121.            END
  122.          END
  123.          CALL CLOSE(list)
  124.          IF verbose THEN DO
  125.            IF counter = 0 THEN moan = list.type 'non chargé.'
  126.            ELSE moan = list.type 'chargé.'
  127.            SAY moan
  128.            IF logFile ~='' THEN CALL WRITELN(log, moan)
  129.          END
  130.        END
  131.      END
  132.    END
  133.  
  134.    IF Account.1.1 = '' THEN DO
  135.       sigh = 'Vous devez configurer votre hôte et le nom d''utilisateur dans SpamFryer.rexx'
  136.       SAY sigh
  137.       IF logFile ~='' THEN CALL writeln(log, sigh)
  138.       IF OPEN(list,accountFile,'R') THEN DO
  139.         sigh = '(ou' accountFile 'si vous préférez les conserver dans des fichiers séparés).'
  140.         SAY sigh
  141.         IF logFile ~='' THEN CALL writeln(log, sigh)
  142.         CALL CLOSE(list)
  143.       END
  144.       IF logFile ~='' THEN CALL CLOSE(log)
  145.      EXIT 5
  146.    END
  147.  
  148.  
  149.  
  150.    
  151.    idx = 1
  152.    DO WHILE LENGTH(Account.idx.1) > 0
  153.  
  154.       pophost  = Account.idx.1
  155.       username = Account.idx.2
  156.       password = Account.idx.3
  157.       
  158.       IF password = '' THEN DO /* Interactive password support by John 'Kwah' Smith */
  159.         CALL addlib('rexxreqtools.library', 0, -30, 37) /* Implicitly uses reqtools.library */
  160.         CALL addlib(LibName, Priority, Offset, Version)
  161.         IF ~show('L', 'rexxreqtools.library') THEN DO
  162.           moan = 'la bibliothèque [rexx]reqtools n''a pas trouvée l''entrée pour le mot de passe.'
  163.           SAY moan
  164.           IF logFile ~='' THEN DO
  165.             IF verbose THEN CALL writeln(log,moan)
  166.             CALL close(log)
  167.           END
  168.           EXIT 20
  169.         END          
  170.         password = rtgetstring( , ('Entrez le mot de passe pour ' || pophost) ,,, 'rtgs_invisible = >> true',)
  171.       END
  172.       
  173.       SAY ''
  174.       SAY 'Vérification du nom d''utilisateur « ' || username || ' ».'
  175.  
  176.       netsend = 'TCP:'||pophost||'/pop3'
  177.       CALL open(net,netsend,'A')
  178.       IF result = 0 THEN DO
  179.          moan = 'Utilisateur « ' || username || ' » : -ERR non trouvé.'
  180.          SAY moan
  181.          IF logFile ~='' THEN DO
  182.             IF verbose THEN CALL writeln(log,moan)
  183.             CALL close(log)
  184.          END
  185.          EXIT 10
  186.       END
  187.       instring=READLN(net)
  188.       CALL test_str(instring)
  189.       CALL writeln(net,'USER '||username||'0d'x)
  190.       instring=READLN(net)
  191.       CALL test_str(instring)
  192.       CALL writeln(net,'PASS '||password||'0d'x)
  193.       instring=READLN(net)
  194.       CALL test_str(instring)
  195.       CALL writeln(net,'STAT'||'0d'x)
  196.       instring=READLN(net)
  197.       CALL test_str(instring)
  198.       info = substr(instring,5,length(instring)-5)
  199.       parse var info nmess ' ' noct
  200.       IF nmess = 0 THEN DO
  201.         SAY 'Il n y a aucun message en attente.'
  202.       END
  203.       ELSE DO
  204.         moan = 'Messages :' nmess ' Octets :' noct
  205.         SAY moan
  206.         IF logFile ~= '' & verbose THEN CALL writeln(log, moan)
  207.  
  208.         /* Clear counters */
  209.  
  210.         nlose = 0
  211.       
  212.         IF logFile ~='' THEN DO /* Per-account headings requested by Elwood */
  213.           CALL writeln(log,'')
  214.           CALL writech(log,'Compte « ' || username || ' » sur «' pophost '» a ' || nmess)
  215.           IF nmess = 1 THEN CALL writeln(log,' message.')
  216.           ELSE CALL writeln(log,' messages.')
  217.         END 
  218.  
  219.  
  220.  
  221.         /* Process all messages */
  222.         DO message = 1 TO nmess
  223.         
  224.           CALL writeln(net,'TOP '||message||' 12'||'0d'x)
  225.  
  226.           instring = ''
  227.           msgdate = ''
  228.           msgfrom = ''
  229.           msgsubj = ''
  230.           msgrepl = ''
  231.           bad = 0
  232.           good = 0
  233.           dating = 0
  234.           datematch = 0
  235.           digitsift = 0
  236.           field = 0
  237.  
  238.           DO UNTIL (LEFT(instring,2)='.' || '0d'x)
  239.  
  240.              instring=READLN(net)
  241.              IF good & msgdate ~='' & msgfrom ~='' & msgsubj ~='' THEN ITERATE 
  242.              /* Speed up if we know it s not spam */
  243.              /* Speed up if no keeplist: IF bad & ~verbose & msgsubj ~='' THEN ITERATE */
  244.  
  245.              inCaps = UPPER(instring)
  246.              IF LEFT(instring,6)='From: ' THEN DO
  247.                field = gFrom
  248.                msgfrom = instring               
  249.                DO i = 1 TO listfield.keep.gFrom
  250.                  IF POS(listpattern.keep.gFrom.i,inCaps)>0 THEN CALL good_one
  251.                END
  252.                DO i = 1 TO listfield.lose.gFrom
  253.                  IF POS(listpattern.lose.gFrom.i,inCaps)>0 THEN CALL bad_one
  254.                END
  255.              END
  256.  
  257.              IF LEFT(instring,4)='To: ' THEN DO
  258.                IF noDigits THEN DO
  259.                   DO i = 0 to 9 /* Reject mails with any digits in recipient address */
  260.                     IF POS(i,instring)>0 THEN DO
  261.                       bad = 1
  262.                       digitsift = digitsift + 1
  263.                       IF verbose THEN DO
  264.                         SAY ' ' message ' perdu(s) pour cause de chiffres dans l''adresse.'
  265.                       END
  266.                     END
  267.                   END
  268.                END
  269.                field = gTo
  270.                DO i = 1 TO listfield.keep.gTo
  271.                  IF POS(listpattern.keep.gTo.i,inCaps)>0 THEN CALL good_one
  272.                END
  273.                DO i = 1 TO listfield.lose.gTo
  274.                  IF POS(listpattern.lose.gTo.i,inCaps)>0 THEN CALL bad_one
  275.                END
  276.              END
  277.  
  278.              IF LEFT(instring,10)='Reply-To: ' THEN DO
  279.                field = gReply
  280.                msgrepl = instring
  281.                DO i = 1 TO listfield.keep.gReply
  282.                  IF POS(listpattern.keep.gReply.i,inCaps)>0 THEN CALL good_one
  283.                END
  284.                DO i = 1 TO listfield.lose.gReply
  285.                  IF POS(listpattern.lose.gReply.i,inCaps)>0 THEN CALL bad_one
  286.                END
  287.              END
  288.  
  289.              IF LEFT(instring,9)='Subject: ' THEN DO
  290.                field = gSubject
  291.                msgsubj = instring
  292.                DO i = 1 TO listfield.keep.gSubject
  293.                  IF POS(listpattern.keep.gSubject.i,inCaps)>0 THEN CALL good_one
  294.                END
  295.                DO i = 1 TO listfield.lose.gSubject
  296.                  IF POS(listpattern.lose.gSubject.i,inCaps)>0 THEN CALL bad_one
  297.                END
  298.              END
  299.  
  300.              IF LEFT(instring,6)='Date: ' THEN msgdate = right(instring,length(instring)-6)
  301.  
  302.              /* Several of the following indicate notorious dating sites */
  303.              IF POS(' DATING ',inCaps)>0 THEN dating = dating + 1;
  304.              IF POS('CREATED BY WOMEN',inCaps)>0 THEN dating = dating + 1;
  305.  
  306.              field = gEarly
  307.              DO i = 1 TO listfield.keep.gEarly
  308.                IF POS(listpattern.keep.gEarly.i,inCaps)>0 THEN CALL good_one
  309.              END
  310.              DO i = 1 TO listfield.lose.gEarly
  311.                IF POS(listpattern.lose.gEarly.i,inCaps)>0 THEN CALL bad_one
  312.              END
  313.  
  314.           END
  315.  
  316.  
  317.  
  318.  
  319.           IF dating>1 THEN DO
  320.             field = gDating /* Require two references to zap a mail */
  321.             CALL bad_one
  322.           END
  323.          
  324.           IF msgfrom = '' THEN msgfrom = msgrepl
  325.           IF (LENGTH(msgfrom) + LENGTH(msgsubj)) = 0 THEN bad = 1 /* © Elwood */
  326.           IF msgfrom = '' THEN msgfrom = 'From: ???????????'
  327.           IF msgdate = '' THEN msgdate = 'Date: ???????????'
  328.           IF msgsubj = '' THEN msgsubj = 'No subject'
  329.           IF length(msgsubj) > lineMax THEN msgsubj = LEFT(msgsubj,lineMax)
  330.  
  331.           IF verbose THEN DO
  332.             SAY ''
  333.             SAY 'Message '||message||' sur' nmess ': '||msgdate
  334.             SAY msgfrom
  335.             SAY msgsubj
  336.           END
  337.  
  338.           IF (good=0) & (bad>0) THEN DO
  339.  
  340.             IF ~verbose THEN SAY "Suppression ("|| message ||"/"|| nmess || ")  »»" msgsubj
  341.  
  342.             IF logFile ~= '' THEN DO
  343.               CALL writeln(log,'Message '||message||': '||msgdate)
  344.               CALL writeln(log,msgfrom)
  345.               CALL writeln(log,msgsubj)
  346.             END
  347.  
  348.             IF bad THEN DO
  349.               CALL writeln(net,'DELE '||message||'0d'x)
  350.               IF verbose THEN DO
  351.                 moan = "$$$$$ Supprimé"
  352.                 SAY moan
  353.                 IF logFile ~= '' THEN CALL writeln(log,moan)
  354.               END
  355.               instring=READLN(net)
  356.               nlose = nlose + 1
  357.               CALL test_str(instring)
  358.               ITERATE message
  359.             END
  360.           END
  361.  
  362.           IF ~verbose THEN ITERATE message
  363.          
  364.           moan = "----- Laissé sur le serveur"
  365.           SAY moan
  366.           IF logFile ~='' & verbose THEN DO
  367.             CALL writeln(log,'Message '||message||': '||msgdate)
  368.             CALL writeln(log,msgfrom)
  369.             CALL writeln(log,msgsubj)
  370.             CALL writeln(log,moan)
  371.           END
  372.        END /* Loop for all messages */
  373.  
  374.  
  375.  
  376.  
  377.        IF nmess ~= 0 THEN DO
  378.          SAY ''
  379.          other = nmess-nlose
  380.          moan = nlose "sur" nmess "courrier"
  381.          IF nmess ~=1 THEN moan = moan || "s"
  382.          moan = "Supprimé(s) :" moan "pour le compte" username "sur" pophost
  383.          SAY moan
  384.          IF logFile ~='' & verbose THEN CALL writeln(log,moan)
  385.        END
  386.  
  387.      END /* Some messages */
  388.      CALL writeln(net,'QUIT'||'0d'x)
  389.      CALL close(net)
  390.      idx = idx + 1
  391.    END  /* do while any accounts unchecked */
  392.    IF logFile ~='' THEN CALL close(log)
  393.    EXIT 0
  394.  
  395.  
  396.  
  397.  
  398. /* good_one keeps track of emails identified by the keeplist    */
  399.  
  400. good_one:
  401.         IF field = 0 THEN RETURN 0 /* Unlikely error */
  402.         good = 1
  403.         IF verbose THEN DO
  404.           SAY '' messsage 'conservé pour' listpattern.keep.field.i
  405.           listpattern.keep.field.i.1 = listpattern.keep.field.i.1 + 1
  406.         END
  407.         return 1
  408.  
  409.  
  410. /* bad_one keeps track of emails identified by the loselist     */
  411.  
  412. bad_one:
  413.         IF field = 0 THEN RETURN 0 /* Error */
  414.         bad = 1
  415.         IF verbose THEN DO
  416.           IF field = gDating THEN DO
  417.             SAY '' message 'perdu pour mauvaise référence de datation'
  418.             datematch = datematch + 1
  419.           END
  420.           ELSE DO
  421.             SAY '' message ' perdu pour' listpattern.lose.field.i
  422.             listpattern.lose.field.i.1 = listpattern.lose.field.i.1 + 1
  423.           END
  424.         END
  425.         return 1
  426.  
  427.  
  428.  
  429.  
  430. /* keep_rule teaches the program a way to identify good emails  */
  431.  
  432. keep_rule:
  433.  
  434.    listerror = 0
  435.    CALL learn_rule arg(1), keep
  436.    IF listerror THEN DO
  437.      sigh = 'ERREUR : Règle "' arg(1) '" dans SpamFryer.rexx ignorée.'
  438.      SAY sigh
  439.      IF logFile ~= '' & verbose THEN CALL WRITELN(log, sigh)
  440.    END
  441.    return 1
  442.  
  443.  
  444. /*  lose_rule teaches the program a way to identify bad emails  */
  445.  
  446. lose_rule:
  447.  
  448.    listerror = 0
  449.    CALL learn_rule arg(1), lose 
  450.    IF listerror THEN DO
  451.      sigh = 'ERREUR : Règle "' arg(1) '" dans SpamFryer.rexx ignorée.'
  452.      SAY sigh
  453.      IF logFile ~= '' & verbose THEN CALL WRITELN(log, sigh)
  454.    END
  455.    return 1
  456.  
  457.  
  458. /*  learn_rule teaches the program a way to categorise emails.  */
  459. /*  The first argument is the rule. The second is the category  */
  460. /*  listerror is set if the rule is not correctly formatted.    */
  461.  
  462. learn_rule:
  463.  
  464.    instring = UPPER(arg(1))
  465.    kind = arg(2)
  466.    PARSE VAR instring word1 word2 .   /* get the first and the second word in the line */
  467.    IF word1 = "//" THEN return 1      /* Allow C++ comments in the configuration lines */
  468.    IF word2 = '' THEN DO
  469.      IF word1 ~= '' THEN listerror = 1   /* Error if there is only one word in the string */
  470.    END
  471.    ELSE DO
  472.      field = 0
  473.      IF RIGHT(word1,1) ~= ':' THEN word1 = word1 || ':'
  474.      IF word1 = 'TO:' THEN field = gTo
  475.      IF word1 = 'FROM:' THEN field = gFrom
  476.      IF word1 = 'REPLY-TO:' THEN field = gReply
  477.      IF word1 = 'REPLYTO:' THEN field = gReply
  478.      IF word1 = 'SUBJECT:' THEN field = gSubject
  479.      IF word1 = 'EARLY-REF:' THEN field = gEarly
  480.      IF word1 = 'EARLYREF:' THEN field = gEarly
  481.      IF field = 0 THEN listerror = 1   /* Error, unexpected first word on line */
  482.      ELSE DO
  483.        instring = STRIP(instring,'L')
  484.        instring = RIGHT(instring,LENGTH(instring)-POS(' ',instring))   /* cut off field parameter, leaving only the search pattern */
  485.        instring = STRIP(instring)
  486.        IF RIGHT(instring,1) = "'" & LEFT(instring,1)="'" THEN instring = STRIP(instring,'B',"'")
  487.        IF RIGHT(instring,1) = '"' & LEFT(instring,1)='"' THEN instring = STRIP(instring,'B','"')       
  488.        listfield.kind.field = listfield.kind.field + 1   /* count entries in each field parameter for each list */
  489.        counter = listfield.kind.field
  490.        listpattern.kind.field.counter = instring   /* Store search pattern */
  491.        listpattern.kind.field.counter.1 = 0    /* No matches yet */
  492.        IF verbose THEN DO
  493.          IF kind = keep THEN sigh = 'KEEP'
  494.          ELSE sigh = 'LOSE'
  495.          SAY sigh counter word1 instring
  496.        END
  497.      END
  498.    END
  499.    return 1
  500.  
  501.  
  502. /*  check_accounts reads POP3 account login details from a file */
  503.  
  504. Check_Accounts:
  505.  
  506.   IF OPEN(list,accountFile,'R') THEN DO
  507.     accounts = 1
  508.     DO WHILE Account.accounts.1 ~=''
  509.       accounts = accounts + 1 /* Skip acounts defined in this file */
  510.     END
  511.  
  512.     userSet = ''
  513.     hostSet = ''
  514.     passSet = ''
  515.     
  516.     counter = count.type
  517.     DO WHILE ~EOF(list)
  518.       instring = READLN(list)
  519.       PARSE VAR instring word1 word2 .   /* get the first and the second word in the line */
  520.       IF word1 ~= "//" & word1 ~= '' THEN DO
  521.         word1 = UPPER(word1)
  522.         field = 0
  523.         IF RIGHT(word1,1) ~= ':' THEN word1 = word1 || ':'
  524.         IF word1 = 'USERNAME:' THEN field = 2
  525.         IF word1 = 'PASSWORD:' THEN field = 3
  526.         IF word1 = 'HOSTNAME:' THEN field = 1
  527.         IF field = 0 THEN DO
  528.           moan = 'ERREUR : élément non reconnu :' word1 'dans' accountFile
  529.           say moan
  530.           IF logFile ~='' THEN CALL WRITELN(log, moan)   
  531.         END
  532.  
  533.        IF RIGHT(word2,1) = "'" & LEFT(word2,1)="'" THEN word2 = STRIP(word2,'B',"'")
  534.        IF RIGHT(word2,1) = '"' & LEFT(word2,1)='"' THEN word2 = STRIP(word2,'B','"')       
  535.         
  536.         /* Make sure each host has one associated username and one or zero passwords */
  537.         ELSE DO
  538.           IF field = 1 THEN DO
  539.             IF hostSet ~= '' THEN DO
  540.               IF userSet = '' THEN DO
  541.                 sigh = 'ERREUR : pas de nom d''utilisateur configuré pour l''hôte' hostSet 'dans' AccountFile
  542.                 SAY sigh
  543.                 IF logFile ~= '' THEN CALL WRITELN(log, sigh)          
  544.               END  
  545.               ELSE DO 
  546.                 accounts = accounts + 1
  547.                 passSet = ''            
  548.                 userSet = ''            
  549.               END        
  550.             END         
  551.             hostSet = word2
  552.           END
  553.           
  554.           IF field = 2 THEN DO
  555.             IF userSet ~= '' THEN DO
  556.               IF hostSet = '' THEN DO
  557.                 sigh = 'ERREUR : pas d''hôte configuré pour l''utilisateur' userSet 'dans' AccountFile
  558.                 SAY sigh
  559.                 IF logFile ~= '' THEN CALL WRITELN(log, sigh)
  560.               END            
  561.               ELSE DO 
  562.                 accounts = accounts + 1
  563.                 hostSet = ''
  564.                 passSet = ''            
  565.               END        
  566.             END         
  567.             userSet = word2
  568.           END
  569.           
  570.           IF field = 3 THEN DO
  571.             IF passSet ~= '' THEN DO
  572.               sigh = 'ERREUR : mots de passes doublés' passSet 'et' word2 'dans' AccountFile
  573.               SAY sigh
  574.               IF logFile ~= '' THEN CALL WRITELN(log, sigh)            
  575.             END
  576.             passSet = word2                    
  577.           END
  578.           
  579.           Account.accounts.field = word2          
  580.         END /* Valid field */          
  581.  
  582.       END /* Not comment or blank line */
  583.     END /* WHILE list */
  584.     CALL CLOSE(list)
  585.     
  586.     IF userSet = '' & hostSet = '' THEN DO
  587.       IF passSet ~= '' THEN DO
  588.         sigh = 'ERREUR : mot de passe' passSet 'dans' AccountFile 'a besoin d''un hôte et d un nom d''utilisateur'
  589.         SAY sigh
  590.         IF logFile ~= '' THEN CALL WRITELN(log, sigh)            
  591.       END   
  592.     END
  593.     ELSE DO
  594.       IF hostSet = '' THEN DO
  595.         sigh = 'ERREUR : pas d''hôte configuré pour l''utilisateur ' userSet 'dans' AccountFile
  596.         SAY sigh
  597.         IF logFile ~= '' THEN CALL WRITELN(log, sigh)            
  598.       END    
  599.       IF userSet = '' THEN DO
  600.         sigh = 'ERREUR : pas d''utilisateur défini pour l''hôte ' hostSet 'dans' AccountFile
  601.         SAY sigh
  602.         IF logFile ~= '' THEN CALL WRITELN(log, sigh)            
  603.       END
  604.     END 
  605.   END
  606.   
  607.   IF verbose THEN DO
  608.     accounts = 1
  609.     DO WHILE Account.accounts.1 ~=''
  610.       sigh = 'Host' Account.accounts.1 'User' Account.accounts.2 'Password' Account.accounts.3
  611.       SAY sigh  
  612.       IF verbose THEN CALL writeln(log, sigh)
  613.       accounts = accounts + 1
  614.     END
  615.   END
  616.  
  617.   return 1
  618.  
  619.    
  620.  
  621.  
  622. /* test_str tests the response from the POP server: +OK or -ERR */
  623.  
  624. test_str:
  625.  
  626.    test = arg(1)
  627.    /* SAY 'Server Response:' test */
  628.    IF POS('+OK',test)~=0 THEN
  629.       return 1
  630.    ELSE
  631.       moan = 'Login' username || ':' test
  632.       SAY moan
  633.       IF logFile ~='' THEN DO
  634.          IF verbose THEN CALL writeln(log, moan)
  635.          CALL close(log)
  636.       END
  637.       CALL writeln(net,'QUIT'||'0d'x)
  638.       CALL close(net)
  639.       EXIT 10
  640.